import oCanvas from 'ocanvas';

/** --- 基本对象信息 --- */
let _nodes = [];
let _elCacheMap = new Map();
let _animationMap = new Map();
let _userCacheMap = new Map();

/**
 * 绑定节点
 * @param nodes [{userId: string, el: object}]
 */
export const initBinds = (nodes) => {
  // 销毁节点(如果有)
  destroyAllCtx();
  // 初始化节点
  initCanvas(nodes);
  // 监听窗口大小变量
  listenResize();
}

/**
 * 设置进度
 * @param userId
 * @param allTime
 * @param stepTime
 */
export const setProcess = (userId, allTime, stepTime) => {
  if(!_elCacheMap.has(userId)) {
    return;
  }

  const {ctx, width, height, dpr} = _elCacheMap.get(userId);
  if(ctx) {
    // 缓存数据对比，如果该用户有缓存数据且局时也未改变，则不做重复动画
    if(allTime === (_userCacheMap.get(userId) || {}).allTime) return;
    // 判断节点是否已经存在
    const animateObj = _animationMap.get(userId);
    if(animateObj) {
      clearProcess(userId);
      animateObj.opacity = 1;
      animateObj.animate({
        start: 360,
      }, {
        easing: 'linear',
        duration: stepTime * 1000,
        queue: 'head-canvas-move',
      });
      _userCacheMap.set(userId, { allTime });
    } else {
      ctx.reset();
      // 边框宽，单位：px
      const boardWidth = 3 * dpr;
      const arc = ctx.display.arc({
        x: Math.floor(width / 2),
        y: Math.floor(height / 2),
        radius: Math.floor(width / 2) - boardWidth / 2,
        start: 360 / allTime * (allTime - stepTime),
        end: 360,
        stroke: `${boardWidth}px linear-gradient(180deg, #6089e8, #41D8DD)`,
        opacity: 1,
      });
      arc.rotate(-90);
      ctx.addChild(arc);
      _animationMap.set(userId, arc);
    }
  }
}

/**
 * 清空进度条
 * @param userId
 */
export const clearProcess = (userId) => {
  const animateObj = _animationMap.get(userId);
  if(animateObj) {
    animateObj.opacity = 0;
    animateObj.stop().animate({
      start: 0,
    }, {
      easing: 'linear',
      duration: 0,
    });
  }
}

/**
 * 重置进度条
 * @param userId
 */
export const resetProcess = (userId) => {
  clearProcess(userId);
  _animationMap.delete(userId);
  _userCacheMap.delete(userId);
}

/**
 * 销毁进度条
 */
export const destroyProcess = () => {
  _elCacheMap && _elCacheMap.clear();
  _animationMap && _animationMap.clear();
  _userCacheMap && _userCacheMap.clear();
}

/**
 * 初始化canvas节点
 * @param nodes
 */
const initCanvas = (nodes) => {
  const dpr = window.devicePixelRatio || 1;

  // 初始化节点
  nodes.forEach(node => {
    const { userId, el, ctx: oldCtx } = node;
    const canvasId = `H-${userId}`;
    el.innerHTML = '';
    oldCtx && oldCtx.destroy();

    const elWidth = el.clientWidth;
    const elHeight = el.clientHeight;

    const canvas = document.createElement('canvas');
    canvas.style.width = `${elWidth}px`;
    canvas.style.height = `${elHeight}px`;
    canvas.style.position = 'absolute';
    canvas.style.zIndex = '1';
    canvas.style.top = '0px';
    canvas.id = canvasId;
    canvas.width = elWidth * dpr;
    canvas.height = elHeight * dpr;

    el.appendChild(canvas);

    const ctx = oCanvas.create({
      canvas: `#${canvasId}`,
      fps: 30,
    });

    // 设置节点
    _elCacheMap.set(userId, {
      ctx: ctx,
      width: elWidth * dpr,
      height: elHeight * dpr,
      dpr: dpr,
    });
    // 移除掉节点
    _animationMap.delete(userId);
  })

  _nodes = nodes;
}

/**
 * 监听窗口大小变动
 */
const listenResize = () => {
  window.addEventListener('resize', e => {
    // 初始化canvas
    initCanvas(_nodes);
  });
}

/**
 * 销毁实例(如果有)
 */
const destroyAllCtx = () => {
  for(let [, attr] of _elCacheMap) {
    const { ctx } = attr;
    ctx && ctx.destroy();
  }
}
